/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package actioncombination.logic.rlmethod;

import actioncombination.common.datastructure.Pair;
import actioncombination.common.value.DoubleValue;
import actioncombination.common.value.Value;
import actioncombination.logic.agent.action.Action;
import actioncombination.logic.agent.AgentState;
import actioncombination.logic.agent.knowledge.*;
import actioncombination.logic.agent.RLAgent;
import actioncombination.problem.gridworld.AgentStateImpl;
import actioncombination.logic.environment.RLEnvironment;
import actioncombination.logic.policy.PolicyStrategy;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import java.util.TreeMap;

/**
 *
 * @author Administrador
 */
public class Qlearning extends RLMethodStrategy {

    public Qlearning(PolicyStrategy polStrategy) {
        super(polStrategy);
    }

    @Override
    public void beginEpisode(RLAgent agent) {
        AgentStateImpl state = (AgentStateImpl) agent.getAgentState();
        state.initState();
        while (!agent.getGoal().isGoalState(state)) {
            step(agent);
        }
        endEpisode();
    }

    //REVISAR
    protected void step(RLAgent agent) {
        //cargo en valuesStates las posibles acciones que puedo tomar
        Map<Action, Value> valuesStates = agent.getAgentState().getActionValues();
        //guardo el estado actual
        AgentStateImpl oldState = (AgentStateImpl) agent.getAgentState();
        //elijo la accion dada por la politica para el estado actual
        Action a = this.getPolStrategy().selectAction(valuesStates);
        //ejecuto la accion y observo el nuevo estado
        AgentStateImpl newState = (AgentStateImpl) agent.execute(a);
        //observo la recompensa del nuevo estado
        DoubleValue reward = ((RLEnvironment) agent.getEnvironment()).getReward(agent);
        //cargo en valuesStates las posibles acciones que puedo tomar
        valuesStates = agent.getAgentState().getActionValues();
        //lo siguiente hasta aMax es para obtener la accion que me devuelve el maximo valor
        //apartir del estado actual
        //elijo la accion con el maximo valor 
        Action aMax = this.getPolStrategy().selectAction(valuesStates, 1);
        //actualizo el viejo estado-accion con la formula de actualizacion
        agent.update(oldState, newState, a, aMax,
                this.getLearningStep(), reward, this.getDiscountRate());

    }

    @Override
    protected void endEpisode() {
        throw new UnsupportedOperationException("Not supported yet.");
    }
}
